home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 039a / mawk.zip / FIN.C < prev    next >
C/C++ Source or Header  |  1991-04-07  |  9KB  |  369 lines

  1.  
  2. /********************************************
  3. fin.c
  4. copyright 1991, Michael D. Brennan
  5.  
  6. This is a source file for mawk, an implementation of
  7. the Awk programming language as defined in
  8. Aho, Kernighan and Weinberger, The AWK Programming Language,
  9. Addison-Wesley, 1988.
  10.  
  11. See the accompaning file, LIMITATIONS, for restrictions
  12. regarding modification and redistribution of this
  13. program in source or binary form.
  14. ********************************************/
  15.  
  16. /*$Log:    fin.c,v $
  17.  * Revision 2.1  91/04/08  08:23:09  brennan
  18.  * VERSION 0.97
  19.  * 
  20. */
  21.  
  22. /* fin.c */
  23.  
  24. #include "mawk.h"
  25. #include "fin.h"
  26. #include "memory.h"
  27. #include "bi_vars.h"
  28. #include "field.h"
  29. #include "symtype.h"
  30. #include "scan.h"
  31. #include <fcntl.h>
  32.  
  33. extern int errno ;
  34. int PROTO(isatty, (int) ) ;
  35. FILE *PROTO(fdopen, (int, char*) ) ;
  36.  
  37. /* statics */
  38. int  PROTO( next_main, (void) ) ;
  39. int  PROTO( is_cmdline_assign, (char *) ) ;
  40.  
  41. FIN  *FINdopen( fd, main_flag )
  42.   int fd , main_flag ;
  43. { register FIN *fin = (FIN *) zmalloc( sizeof(FIN) ) ;
  44.  
  45.   fin->fd = fd ;
  46.  
  47.   if ( main_flag )
  48.   { fin->flags = MAIN_FLAG ;
  49.     fin->buffp = fin->buff = main_buff ;
  50.   }
  51.   else
  52.   { 
  53.     fin->flags = 0 ;
  54.     fin->buffp = fin->buff = (char *) zmalloc(BUFFSZ+1) ;
  55.   }
  56.   *fin->buffp = 0 ;
  57.  
  58.   if ( isatty(fd) && rs_shadow.type == SEP_CHAR 
  59.        && rs_shadow.c == '\n' )
  60.   {
  61.     /* interactive, i.e., line buffer this file */
  62.     if ( fd == 0 ) fin->fp = stdin ;
  63.     else
  64.     if ( !(fin->fp = fdopen(fd, "r")) )
  65.     { errmsg(errno, "fdopen failed") ; exit(1) ; }
  66.   }
  67.   else  fin->fp = (FILE *) 0 ;
  68.  
  69.   return fin ;
  70. }
  71.  
  72. FIN  *FINopen( filename, main_flag )
  73.   char *filename ;
  74.   int main_flag ;
  75. { int fd ;
  76.  
  77.   if ( (fd = open( filename , O_RDONLY, 0 )) == -1 )
  78.   { errmsg( errno, "cannot open %s" , filename ) ;
  79.     return (FIN *) 0 ; }
  80.  
  81.   else  return  FINdopen( fd, main_flag ) ;
  82. }
  83.  
  84. void  FINclose( fin )
  85.   register FIN *fin ;
  86. {
  87.   if ( ! (fin->flags & MAIN_FLAG) )  
  88.         zfree(fin->buff, BUFFSZ+1) ;
  89.  
  90.   if ( fin->fd )  
  91.         if ( fin->fp )  (void) fclose(fin->fp) ;
  92.         else  (void) close(fin->fd) ;
  93.  
  94.   zfree( fin , sizeof(FIN) ) ;
  95. }
  96.  
  97. /* return one input record as determined by RS,
  98.    from input file (FIN)  fin
  99. */
  100.  
  101. char *FINgets( fin, len_p )
  102.   FIN *fin ;
  103.   unsigned *len_p ;
  104. { register char *p, *q ;
  105.   unsigned match_len ;
  106.   unsigned r ;
  107.  
  108. restart :
  109.  
  110.   if ( ! (p = fin->buffp)[0] )  /* need a refill */
  111.   { 
  112.     if ( fin->flags & EOF_FLAG )
  113.         if ( (fin->flags & MAIN_FLAG) && next_main() )  goto restart ;
  114.         else
  115.         { *len_p = 0 ; return (char *) 0 ; }
  116.         
  117.     if ( fin->fp ) /* line buffering */
  118.       if ( ! fgets(fin->buff, BUFFSZ+1, fin->fp) )
  119.       {
  120.         fin->flags |= EOF_FLAG ;
  121.         fin->buff[0] = 0 ;
  122.         fin->buffp = fin->buff ;
  123.         goto restart ;  /* might be main_fin */
  124.       }
  125.       else  /* return this line */
  126.       {
  127.         if ( !(p = strchr(fin->buff, '\n')) )
  128.              p = fin->buff + BUFFSZ + 1 ; /* unlikely to occur */
  129.  
  130.         *p = 0 ; *len_p = p - fin->buff ;
  131.         fin->buffp = p ;
  132.         return  fin->buff ;
  133.       }
  134.     else  /* block buffering */
  135.     {
  136.       if ( (r = fillbuff(fin->fd, fin->buff, BUFFSZ)) == 0 )
  137.       {
  138.         fin->flags |= EOF_FLAG ;
  139.         fin->buffp = fin->buff ;
  140.         goto restart ; /* might be main */
  141.       }
  142.       else
  143.       if ( r < BUFFSZ )  fin->flags |= EOF_FLAG ;
  144.  
  145.       p = fin->buffp = fin->buff ;
  146.     }
  147.   }
  148.  
  149. retry: 
  150.  
  151.   switch( rs_shadow.type )
  152.   {
  153.     case SEP_CHAR :
  154.             q = strchr(p, rs_shadow.c) ;
  155.             match_len = 1 ;
  156.             break ;
  157.  
  158.     case SEP_STR  :
  159.             q = str_str(p, ((STRING *) rs_shadow.ptr)->str,
  160.                 match_len = ((STRING *) rs_shadow.ptr)->len ) ;
  161.             break ;
  162.  
  163.     case SEP_RE :
  164.             q = re_pos_match(p, rs_shadow.ptr, &match_len) ;
  165.             /* if the match is at the end, there might be more
  166.                still to be read */
  167.             if ( q && q[match_len] == 0 &&
  168.                  p != fin->buff )  q = (char *) 0 ;
  169.             break ;
  170.             
  171.     default :
  172.             bozo("type of rs_shadow") ;
  173.   }
  174.   if ( q )
  175.   {  /* the easy and normal case */
  176.      *q = 0 ;  *len_p = q - p ;
  177.      fin->buffp = q + match_len  ;
  178.      return p ;
  179.   }
  180.  
  181.   if ( p == fin->buff )  /* last line or one huge (truncated) line */
  182.   { *len_p = r = strlen(p) ;  fin->buffp = p + r ;
  183.     /* treat truncated case as overflow */
  184.     if ( r == BUFFSZ ) 
  185.     { /* overflow, update NR and FNR */
  186.       cast2_to_d(bi_vars+NR) ;
  187.       bi_vars[NR].dval += 1.0 ;
  188.       bi_vars[FNR].dval += 1.0 ;
  189.       rt_overflow("maximum record length" , BUFFSZ) ;
  190.     }
  191.      return p ;
  192.   }
  193.  
  194.   /* move a partial line to front of buffer and try again */
  195.   p = (char *) memcpy( fin->buff, p, r = strlen(p) ) ;
  196.   q = p+r ; 
  197.   if ( fin->flags & EOF_FLAG ) *q = 0 ;
  198.   else 
  199.   { unsigned rr = BUFFSZ - r ;
  200.  
  201.     if ( (r = fillbuff(fin->fd, q, rr)) < rr ) fin->flags |= EOF_FLAG ;
  202.   }
  203.   goto retry ;
  204. }
  205.  
  206. /*--------
  207.   target is big enough to hold size + 1 chars 
  208.   on exit the back of the target is zero terminated
  209.  *--------------*/
  210. unsigned  fillbuff(fd, target, size)
  211.   int fd ;
  212.   register char *target ;
  213.   unsigned size ;
  214. { register int r ;
  215.   unsigned entry_size = size ;
  216.  
  217.   while ( size )
  218.     switch( r = read(fd, target, size) )
  219.     { case -1 :
  220.         errmsg(errno, "read error on file") ;
  221.         exit(1) ;
  222.  
  223.       case 0 :
  224.         goto out ;
  225.  
  226.       default :
  227.         target += r ; size -= r ;
  228.         break ;
  229.     }
  230.  
  231. out :
  232.   *target = 0 ;
  233.   return  entry_size - size ;
  234. }
  235.  
  236. /* main_fin is a handle to the main input stream
  237.    == -1 if never tried to open 
  238.    == 0  if end of stream
  239.       otherwise active    */
  240. FIN *main_fin = (FIN *) -1 ;
  241. ARRAY   Argv ;   /* to the user this is ARGV  */
  242. static int argi = 1 ;  /* index of next ARGV[argi] to try to open */
  243.  
  244. int  open_main()  /* boolean return, true if main is open */
  245.   if ( bi_vars[ARGC].type == C_DOUBLE && bi_vars[ARGC].dval == 1.0 )
  246.   { cell_destroy( bi_vars + FILENAME ) ;
  247.     bi_vars[FILENAME].type = C_STRING ;
  248.     bi_vars[FILENAME].ptr = (PTR) new_STRING( "-") ;
  249.     main_fin = FINdopen(0, 1) ;
  250.     return  1 ;
  251.   }
  252.   else    return next_main() ;
  253. }
  254.  
  255. static  int  next_main()
  256. { char xbuff[16] ;
  257.   register CELL *cp ;
  258.   STRING *sval ;
  259.   CELL   argc ;  /* temp copy of ARGC */
  260.   CELL   tc ;    /* copy of ARGV[argi] */
  261.   double d_argi ;
  262.  
  263. #ifdef  DEBUG
  264.   if ( ! main_fin ) bozo("call to next_main with dead main") ;
  265. #endif
  266.  
  267.   tc.type = C_NOINIT ;
  268.  
  269.   if ( main_fin != (FIN *)-1 )  FINclose(main_fin) ;
  270.   cell_destroy( bi_vars + FILENAME ) ;
  271.   cell_destroy( bi_vars + FNR ) ;
  272.   bi_vars[FNR].type = C_DOUBLE ;
  273.   bi_vars[FNR].dval = 0.0 ;
  274.  
  275.   if ( cellcpy(&argc, &bi_vars[ARGC])->type != C_DOUBLE )
  276.           cast1_to_d(&argc) ;
  277.   xbuff[1] = 0 ;
  278.   d_argi = (double) argi ;
  279.  
  280.   while ( d_argi < argc.dval )
  281.   {
  282.     if ( argi < 10 )  xbuff[0] = argi + '0' ;
  283.     else  (void) sprintf(xbuff, "%u", argi) ;
  284.  
  285.     argi++ ; d_argi += 1.0 ;
  286.     sval = new_STRING(xbuff) ;
  287.  
  288.     /* the user might have changed ARGC or deleted 
  289.        ARGV[argi] -- test for existence without side effects */
  290.     
  291.     if ( ! array_test(Argv, sval) )
  292.     { free_STRING(sval) ; continue ; }
  293.  
  294.     cp = array_find( Argv, sval, 0) ;
  295.     free_STRING(sval) ;
  296.  
  297.     /* make a copy so we can cast w/o side effect */
  298.     cell_destroy(&tc) ;
  299.     cp = cellcpy(&tc, cp) ;
  300.     if ( cp->type < C_STRING )  cast1_to_s(cp) ;
  301.     if ( string(cp)->len == 0 )  continue ;
  302.  
  303.     if ( string(cp)->len == 1 && string(cp)->str[0] == '-' )
  304.     { /* input from stdin */
  305.       main_fin = FINdopen(0,1) ;
  306.     }
  307.     else  /* it might be a command line assignment */
  308.     if ( is_cmdline_assign(string(cp)->str) )  continue ;
  309.  
  310.     else /* try to open it */
  311.     if ( ! (main_fin = FINopen( string(cp)->str, 1 )) ) continue ;
  312.  
  313.     /* success */
  314.     (void) cellcpy( &bi_vars[FILENAME] , cp ) ;
  315.     free_STRING( string(cp) ) ;
  316.     return 1 ;
  317.   }
  318.   /* failure */
  319.   bi_vars[FILENAME].type = C_STRING ;
  320.   bi_vars[FILENAME].ptr = (PTR) new_STRING( "" ) ;
  321.   main_fin = (FIN *) 0 ;
  322.   cell_destroy(&tc) ;
  323.   return 0 ;
  324. }
  325.     
  326.  
  327. static int is_cmdline_assign(s)
  328.   char *s ;
  329. { char *q;
  330.   unsigned char *p ;
  331.   int c ;
  332.   SYMTAB *stp ;
  333.   CELL *cp ;
  334.  
  335.   if ( scan_code[*(unsigned char *)s] != SC_IDCHAR 
  336.        || !(q = strchr(s,'=')) ) return 0 ;
  337.  
  338.   p = (unsigned char *)s+1 ;
  339.   while ( (c = scan_code[*p]) == SC_IDCHAR || c == SC_DIGIT ) p++ ;
  340.  
  341.   if ( (char *)p < q )  return 0 ;
  342.  
  343.   *q = 0 ;
  344.   stp = find(s) ;
  345.  
  346.   switch( stp->type )
  347.   {
  348.     case  ST_NONE :
  349.         stp->type = ST_VAR ;
  350.         stp->stval.cp = cp = new_CELL() ;
  351.         break ;
  352.  
  353.     case  ST_VAR :
  354.         cp = stp->stval.cp ;
  355.         break ;
  356.  
  357.     default :
  358.         rt_error(
  359.           "cannot command line assign to %s\n\t- type clash or keyword" 
  360.           , s ) ;
  361.   }
  362.   
  363.   *q++ = '=' ;
  364.   cp->ptr = (PTR) new_STRING(q) ;
  365.   check_strnum(cp) ;
  366.   return 1 ;
  367. }
  368.